{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Aggregating trajectories\n",
    "\n",
    "<img align=\"right\" src=\"https://anitagraser.github.io/movingpandas/assets/img/movingpandas.png\">\n",
    "\n",
    "[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/anitagraser/movingpandas-examples/main?filepath=1-tutorials/9-aggregating-trajectories.ipynb)\n",
    "[![IPYNB](https://img.shields.io/badge/view-ipynb-hotpink)](https://github.com/anitagraser/movingpandas-examples/blob/main/1-tutorials/9-aggregating-trajectories.ipynb)\n",
    "[![HTML](https://img.shields.io/badge/view-html-green)](https://anitagraser.github.io/movingpandas-website/1-tutorials/9-aggregating-trajectories.html)\n",
    "\n",
    "The aggregation approach implemented in TrajectoryCollectionAggregator is based on Andrienko, N., & Andrienko, G. (2011). Spatial generalization and aggregation of massive movement data. IEEE Transactions on visualization and computer graphics, 17(2), 205-219. and consists of the following main steps:\n",
    "\n",
    "1. Extracting characteristic points from the trajectories\n",
    "2. Grouping the extracted points by spatial proximity\n",
    "3. Computing group centroids and corresponding Voronoi cells\n",
    "4. Dividing trajectories into segments according to the Voronoi cells\n",
    "5. Counting transitions from one cell to another"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import geopandas as gpd\n",
    "from geopandas import GeoDataFrame, read_file\n",
    "from shapely.geometry import Point, LineString, Polygon\n",
    "from datetime import datetime, timedelta\n",
    "from holoviews import opts, dim\n",
    "import movingpandas as mpd\n",
    "\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "\n",
    "mpd.show_versions()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "FSIZE = 350"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gdf = read_file('../data/geolife_small.gpkg')\n",
    "traj_collection = mpd.TrajectoryCollection(gdf, 'trajectory_id', t='t')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "traj_collection.hvplot(line_width=7.0, tiles='StamenTonerBackground', width=FSIZE, height=FSIZE)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## TrajectoryCollectionAggregator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "help(mpd.TrajectoryCollectionAggregator)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Generalizing the trip trajectories significantly speeds up the following aggregation step."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "generalized = mpd.MinDistanceGeneralizer(traj_collection).generalize(tolerance=100)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "aggregator = mpd.TrajectoryCollectionAggregator(generalized, max_distance=1000, min_distance=100, min_stop_duration=timedelta(minutes=5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pts = aggregator.get_significant_points_gdf()\n",
    "clusters = aggregator.get_clusters_gdf()\n",
    "( pts.hvplot(geo=True, tiles='StamenTonerBackground', width=FSIZE, height=FSIZE) * \n",
    "  clusters.hvplot(geo=True, color='red' ) )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "flows = aggregator.get_flows_gdf()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "( flows.hvplot(geo=True, hover_cols=['weight'], line_width=dim('weight')*7, color='#1f77b3', tiles='StamenTonerBackground') * \n",
    "  clusters.hvplot(geo=True, color='red', size=dim('n') ) )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
